package simpledb;

import java.util.*;

/**
 * Filter is an operator that implements a relational select.
 * 继承于一个抽象类Operator，Operator实现了基本的hasNext(),next(),clode(),open()
 * hasNext(),next()具体通过哪种规则fetchNext()来过滤元组还需要在它的子类Filter中实现,还包括一些修改迭代器，返回具体的TupleDesc
 *
 */
public class Filter extends Operator {

    private static final long serialVersionUID = 1L;

    private OpIterator child;
    private Predicate predicate;
    private TupleDesc tupleDesc;

    //使用一个TupleIterator来存储所有符合谓词条件的元组，相当于缓存
    private TupleIterator tupleIterator;
    /**
     * Constructor accepts a predicate to apply and a child operator to read
     * tuples to filter from.
     * 
     * @param p
     *            The predicate to filter tuples with
     *            过滤元组的谓词
     * @param child
     *            The child operator
     */
    public Filter(Predicate p, OpIterator child) {
        this.predicate = p;
        this.child = child;
        this.tupleDesc = child.getTupleDesc();
        // some code goes here
    }

    public Predicate getPredicate() {
        // some code goes here
        return predicate;
    }

    public TupleDesc getTupleDesc() {
        // some code goes here
        return tupleDesc;
    }

    public TupleIterator filter(OpIterator child,Predicate predicate) throws TransactionAbortedException, DbException {
        List<Tuple> tuples = new ArrayList<>();
        while(child.hasNext())
        {
            Tuple t = child.next();
            if(predicate.filter(t))
            {
                tuples.add(t);
            }
        }
        return new TupleIterator(tupleDesc,tuples);
    }

    /*
    open(),close()是否需要由父及子来调用
    对tupleIterator进行一个初始化，也就是将所有满足谓词条件的元组都存入TupleIterator中的实现Iterable接口的结构（如ArrayList）
     */
    public void open() throws DbException, NoSuchElementException,
            TransactionAbortedException {
        // some code goes here
        super.open();
        child.open();
        tupleIterator = filter(child,predicate);
        tupleIterator.open();
    }

    public void close() {
        // some code goes here
        super.close();
        child.close();
        tupleIterator.close();
    }

    public void rewind() throws DbException, TransactionAbortedException {
        // some code goes here
        child.rewind();
        tupleIterator.rewind();
    }

    /**
     * AbstractDbIterator.readNext implementation. Iterates over tuples from the
     * child operator, applying the predicate to them and returning those that
     * pass the predicate (i.e. for which the Predicate.filter() returns true.)
     * 
     * @return The next tuple that passes the filter, or null if there are no
     *         more tuples
     * @see Predicate#filter
     * 通过一个predicate来过滤元组，找到符合条件的元组
     */
    protected Tuple fetchNext() throws NoSuchElementException,
            TransactionAbortedException, DbException {
        // some code goes here
        if(tupleIterator.hasNext())
        {
            return tupleIterator.next();
        }
        return null;
    }

    @Override
    public OpIterator[] getChildren() {
        // some code goes here
        return new OpIterator[]{child};
    }

    @Override
    public void setChildren(OpIterator[] children) {
        // some code goes here
        child = children[0];
    }

}
